﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.OleDb;
using System.Data;
using System.Diagnostics.Contracts;

namespace Numero2DataSet
{
    public class ConnexionDB : IDisposable
    {
        private const string CHAINE_CONNEXION = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=cours.mdb";
        private static ConnexionDB maConnexion;
        private OleDbConnection oleConnexion;
        private DataSet dataSet;

        public DataSet DataSet
        {
            get 
            {
                if (dataSet == null)
                {
                    dataSet = new DataSet();
                }
                return dataSet; 
            }
        }

        public DataSet ResetDataSet()
        {
            Contract.Requires(OleConnexion != null, "La connexion doit être définie pour exécuter une requête");

            DataSet.Reset();

            OleDbDataAdapter dataAdapter;
            dataAdapter = new OleDbDataAdapter();
            dataAdapter.SelectCommand = new OleDbCommand("SELECT * FROM cours", oleConnexion);
            dataAdapter.Fill(dataSet, "cours");
            dataAdapter.SelectCommand = new OleDbCommand("SELECT * FROM etudiants", oleConnexion);
            dataAdapter.Fill(dataSet, "etudiants");
            dataAdapter.SelectCommand = new OleDbCommand("SELECT * FROM resultats", oleConnexion);
            dataAdapter.Fill(dataSet, "resultats");

            return dataSet;
        }

        public OleDbConnection OleConnexion
        {
            get
            {
                return oleConnexion;
            }
        }

        public static ConnexionDB Creer()
        {
            Contract.Requires(!String.IsNullOrEmpty(CHAINE_CONNEXION), "La chaîne de connexion doit être définie.");
            Contract.Ensures(maConnexion.oleConnexion != null, "Erreur à la création de la connexion.");

            if (maConnexion == null)
            {
                maConnexion = new ConnexionDB();
                maConnexion.oleConnexion = new OleDbConnection(CHAINE_CONNEXION);
            }
            return maConnexion;
        }

        public static void Detruire()
        {
            Contract.Ensures(maConnexion == null, "Erreur à la destruction de la connexion.");

            if (maConnexion != null && maConnexion.oleConnexion.State == System.Data.ConnectionState.Closed)
            {
                maConnexion.Dispose();
                maConnexion = null;
            }
        }

        public int ExecuterScalaire(string commande)
        {
            Contract.Requires(OleConnexion != null, "La connexion doit être définie pour exécuter une requête");

            int resultat;
            oleConnexion.Open();
            OleDbCommand maCmd = new OleDbCommand(commande, oleConnexion);
            resultat = (int)maCmd.ExecuteScalar();
            oleConnexion.Close();
            return resultat;
        }

        public List<Dictionary<string, object>> ExecuterReader(string commande, List<OleDbParameter> parametres = null)
        {
            Contract.Requires(OleConnexion != null, "La connexion doit être définie pour exécuter une requête");

            List<Dictionary<string, object>> listeRetour = new List<Dictionary<string, object>>();
            OleDbDataReader reader;
            oleConnexion.Open();
            OleDbCommand maCmd = new OleDbCommand(commande, oleConnexion);
            if (parametres != null)
            {
                foreach(OleDbParameter parametre in parametres)
                {
                    maCmd.Parameters.Add(parametre);
                }
            }
            reader = maCmd.ExecuteReader();
            while (reader.Read())
            {
                Dictionary<string, object> dictionnaireDansListe = new Dictionary<string, object>();
                listeRetour.Add(dictionnaireDansListe);
                for (int ctr = 0; ctr < reader.FieldCount; ctr++)
                {
                    dictionnaireDansListe.Add(reader.GetName(ctr), reader[ctr]);
                }
            }
            maConnexion.oleConnexion.Close();
            return listeRetour;
        }

        public void Dispose()
        {
            GC.SuppressFinalize(this);
        }
    }
}
